package com.cnpc.framework.base.utils;

import com.google.gson.Gson;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.lang.reflect.Type;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class HttpClient {
    private final static Logger LOGGER = Logger.getLogger(HttpClient.class);

    /**
     * 发送post 请求
     *
     * @param remoteQueryParams
     * @return
     */
    public static String restTemplatePostJson(String url, Map<String, Object> remoteQueryParams) throws Exception {

        RestTemplate restTemplate = getRestTemplate();
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
        headers.setContentType(type);
        headers.add("Accept", org.springframework.http.MediaType.APPLICATION_JSON.toString());
        String jsonParams = new Gson().toJson(remoteQueryParams);
        HttpEntity<String> formEntity = new HttpEntity<String>(jsonParams, headers);
        String result = restTemplate.postForObject(url, formEntity, String.class);
        System.out.println(result);
        return result;

    }

    public static String restTemplatePostJson(String url, Object obj) throws Exception {
        System.out.println("url:"+url);
        RestTemplate restTemplate = getRestTemplate();
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
        headers.setContentType(type);
        headers.add("Accept", org.springframework.http.MediaType.APPLICATION_JSON.toString());
        String jsonParams ;
        if (obj instanceof String){
            jsonParams =obj.toString();
        }else {
            jsonParams = new Gson().toJson(obj);
        }
        System.out.println(jsonParams);
        HttpEntity<String> formEntity = new HttpEntity<String>(jsonParams, headers);
        String result = restTemplate.postForObject(url, formEntity, String.class);
        System.out.println(result);
        return result;

    }

    /**
     * 发送post 请求
     *
     * @param params
     * @return
     */
    public static <T> T  restTemplatePost(String url, Map<String, Object> params, Class<T> clazz) throws Exception {

        RestTemplate restTemplate = getRestTemplate();
        LOGGER.info("url:"+url);
        LOGGER.info("params:"+params);
        HttpEntity<MultiValueMap<String, Object>> httpEntity = null;
        if (params != null) {
            Set<String> keySet = params.keySet();
            if (keySet.size() > 0) {
                MultiValueMap<String, Object> requestParams = new LinkedMultiValueMap<>();
                for (String key : keySet) {
                    requestParams.add(key,params.get(key)+"");
                }

                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
                httpEntity = new HttpEntity<>(requestParams, headers);
            }
        }
        if (String.class.getSimpleName().equals(clazz.getSimpleName())) {
            return restTemplate.postForObject(url, httpEntity, clazz);
        }
        String response = restTemplate.postForObject(url, httpEntity, String.class);
        System.out.println(response);
        return new Gson().fromJson(response,clazz);

    }

    public static String  restTemplatePost(String url, String date) throws Exception {

        RestTemplate restTemplate = getRestTemplate();
        LOGGER.info("url:"+url);
        LOGGER.info("date:"+date);

        String response = restTemplate.postForObject(url, date, String.class);
        System.out.println(response);
        return response;

    }

    public static <T> T  restTemplatePost(String url, Map<String, Object> params, Type typeOfT) throws Exception {

        RestTemplate restTemplate = getRestTemplate();
        LOGGER.info("url:"+url);
        LOGGER.info("params:"+params);
        HttpEntity<MultiValueMap<String, Object>> httpEntity = null;
        if (params != null) {
            Set<String> keySet = params.keySet();
            if (keySet.size() > 0) {
                MultiValueMap<String, Object> requestParams = new LinkedMultiValueMap<>();
                for (String key : keySet) {
                    requestParams.add(key,params.get(key)+"");
                }

                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
                httpEntity = new HttpEntity<>(requestParams, headers);
            }
        }
        String response = restTemplate.postForObject(url, httpEntity, String.class);
        System.out.println(response);
        return new Gson().fromJson(response,typeOfT);

    }

    public static String restTemplateGet(String url, Map<String, Object> remoteQueryParams) throws Exception {
        LOGGER.info("url:"+url);
        LOGGER.info("params:"+remoteQueryParams);
        if (remoteQueryParams != null) {
            Set<String> keySet = remoteQueryParams.keySet();
            if (keySet.size() > 0) {
                StringBuilder sb = new StringBuilder("");
                sb.append(url).append("?");
                for (String key : keySet) {
                    sb.append(key)
                            .append("=")
                            .append(remoteQueryParams.get(key))
                            .append("&");
                }
                sb.deleteCharAt(sb.length() - 1);
                url = sb.toString();
            }
        }
        System.out.println("url:" + url);
        RestTemplate restTemplate = getRestTemplate();

        String response = restTemplate.getForObject(url, String.class);
        System.out.println(response);
        return response;

    }

    public static <T> T restTemplateGet(String url, Map<String, Object> remoteQueryParams, Class<T> clazz) throws Exception {
        LOGGER.info("url:"+url);
        LOGGER.info("params:"+remoteQueryParams);
        if (remoteQueryParams != null) {
            Set<String> keySet = remoteQueryParams.keySet();
            if (keySet.size() > 0) {
                StringBuilder sb = new StringBuilder("");
                sb.append(url).append("?");
                for (String key : keySet) {
                    sb.append(key)
                            .append("=")
                            .append(remoteQueryParams.get(key))
                            .append("&");
                }
                sb.deleteCharAt(sb.length() - 1);
                url = sb.toString();
            }
        }
        System.out.println("url:" + url);
        RestTemplate restTemplate = getRestTemplate();
        if (String.class.getSimpleName().equals(clazz.getSimpleName())) {
            return restTemplate.getForObject(url, clazz);
        }
        String response = restTemplate.getForObject(url, String.class);
        System.out.println(response);
        return new Gson().fromJson(response,clazz);

    }

    public static <T> T restTemplateGet(String url, Map<String, Object> remoteQueryParams,Type typeOfT) throws Exception {
        LOGGER.info("url:"+url);
        LOGGER.info("params:"+remoteQueryParams);
        if (remoteQueryParams != null) {
            Set<String> keySet = remoteQueryParams.keySet();
            if (keySet.size() > 0) {
                StringBuilder sb = new StringBuilder("");
                sb.append(url).append("?");
                for (String key : keySet) {
                    sb.append(key)
                            .append("=")
                            .append(remoteQueryParams.get(key))
                            .append("&");
                }
                sb.deleteCharAt(sb.length() - 1);
                url = sb.toString();
            }
        }
        System.out.println("url:" + url);
        RestTemplate restTemplate = getRestTemplate();

        String response = restTemplate.getForObject(url, String.class);
        System.out.println(response);
        return new Gson().fromJson(response,typeOfT);

    }

    private static RestTemplate getRestTemplate() {
        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
        requestFactory.setConnectTimeout(60*1000);
        requestFactory.setReadTimeout(60*1000);
        RestTemplate restTemplate = new RestTemplate(requestFactory);
        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        return restTemplate;
    }

    public static RestTemplate getRestTemplate1() throws Exception{
        TrustStrategy acceptingTrustStrategy = (new TrustStrategy() {
            @Override
            public boolean isTrusted(X509Certificate[] x509Certificates, String authType) throws CertificateException {
                return true;
            }
        });
        SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
        SSLConnectionSocketFactory connectionSocketFactory = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier());

        HttpClientBuilder httpClientBuilder = HttpClients.custom();
        httpClientBuilder.setSSLSocketFactory(connectionSocketFactory);
        CloseableHttpClient httpClient = httpClientBuilder.build();
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        factory.setHttpClient(httpClient);

        RestTemplate restTemplate = new RestTemplate(factory);

        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));

        List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
        for (HttpMessageConverter<?> c : messageConverters) {
            if (c instanceof StringHttpMessageConverter) {
                ((StringHttpMessageConverter) c).setWriteAcceptCharset(false);
            }
        }

        return restTemplate;
    }


    public static String httpPost(String url, Map<String, String> params) {
        LOGGER.info("url:"+url);
        LOGGER.info("params:"+params);
        CloseableHttpClient httpclient = HttpClients.createDefault();
        Set<String> keySet = params.keySet();
        if (url != null & keySet != null) {
            try {
                RequestBuilder builder = RequestBuilder.post().setUri(url);
                for (String key : keySet) {

                    builder.addParameter(key, params.get(key));
                }
                HttpUriRequest login = builder.build();
                CloseableHttpResponse response = httpclient.execute(login);
                try {
                    org.apache.http.HttpEntity entity = response.getEntity();
                    if (entity != null) {
                        return EntityUtils.toString(entity, "utf-8");
                    }

                } finally {

                    response.close();
                }

            } catch (IOException e) {
                LOGGER.error(e.getMessage());
                return null;
            } finally {
                // 关闭连接,释放资源
                try {
                    httpclient.close();
                } catch (IOException e) {
                    LOGGER.error(e.getMessage());
                }
            }

        }
        return null;
    }
    public static Map<String, String> restTemplatePostForLocation(String url, Map<String, String> params, Map<String, String> headerParams) {
        try{
            System.out.println("url:"+url);
            RestTemplate restTemplate = null;
            if (url.startsWith("https")) {
                restTemplate = getRestTemplate1();
            }else {
                restTemplate = getRestTemplate();
            }
            URI uri = restTemplate.postForLocation(url,params);

            return getQueryParams(uri.getQuery());
        }catch (Exception ex){
            ex.printStackTrace();
        }
        return  null;

    }

    public static Map<String, String> getQueryParams(String queryStr){
        Map<String, String> result = new HashMap<>();
        for (String kp : queryStr.split("&")) {
            System.out.println(kp);
            String key = kp.split("=")[0];
            String value = kp.split("=").length>1?kp.split("=")[1]:null;
            result.put(key,value);
        }

        return result;
    }
}
